Skip to content

Add detector-to-decision layer for region-based VLM inference - #37

Open
r33drichards wants to merge 9 commits into
mainfrom
claude/youthful-newton-mjsunc
Open

r33drichards wants to merge 9 commits into
mainfrom
claude/youthful-newton-mjsunc

Conversation

@r33drichards

Copy link
Copy Markdown
Owner

Summary

This PR introduces a new laya.regions module that bridges object detectors and the VLM decision model, enabling two key workflows: selecting one region from a detector's output, and mapping decisions across multiple regions via cropping.

Key Changes

  • New laya/regions.py module (511 lines):

    • Region dataclass representing detections with pixel boxes, optional labels, scores, and masks
    • Detector adapters (as_regions, from_ultralytics, from_supervision, from_sam, from_omniparser, from_hf_pipeline) supporting YOLO, RT-DETR, RF-DETR, SAM, OmniParser, and transformers pipelines
    • select() function for one-choice questions over regions with Set-of-Mark visualization and knockout rounds for large region counts
    • map_regions() function for applying questions to each region's crop
    • stream() function for processing frame sequences with background detection
    • RegionPipeline class wrapping the above for convenient chaining
    • draw_marks() for numbered region visualization
  • Comprehensive test suite (tests/test_regions.py, 220 lines):

    • Tests for all detector adapters
    • Tests for region cropping, selection, mapping, and streaming
    • End-to-end test with SmolVLM-256M checkpoint
  • Benchmark probes for measuring effectiveness:

    • benchmarks/marks_probe.py: Synthetic Set-of-Mark readability test (digit and colored box recognition)
    • benchmarks/crop_probe.py: COCO ground-truth crop verification and 8-way classification
    • benchmarks/zoom_probe.py: Oracle zoom ceiling on V*Bench small objects
    • benchmarks/zoom_search_probe.py: Glance-then-zoom search strategies
  • Documentation (site-docs/how-to/detector-regions.md):

    • Usage guide for plugging in detectors
    • Examples of select() and map_regions() workflows
    • Explanation of Set-of-Mark visualization and knockout rounds
  • Module exports: Added Region and RegionPipeline to laya/__init__.py

Notable Implementation Details

  • Duck-typed detector support: No hard dependencies on detector libraries; adapters work via attribute inspection
  • Knockout algorithm: Handles >10 regions by grouping into rounds, with winners advancing until one remains
  • Crop padding: Configurable padding and minimum size for region crops to ensure readable input
  • Format versioning: REGIONS_FORMAT_VERSION tracks changes to mark drawing and option formatting
  • Streaming with background detection: stream() runs detection on a background thread while the decision model processes the current frame, with optional frame dropping for real-time constraints
  • Calibration caveat: Documentation notes that no released checkpoint was trained on marked regions or detector crops, so accuracy must be measured per task

https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H

Work-in-progress sketch, not final: the design is still being brainstormed.
Adds duck-typed adapters from detector outputs (OmniParser, ultralytics,
supervision/RF-DETR, SAM masks, transformers pipelines) to Region objects,
select() (Set-of-Mark choice over boxes with a knockout for many boxes),
map_regions() (the same questions per crop) and stream() (background
detection with optional stale-frame dropping), plus a draft how-to page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
benchmarks/marks_probe.py asks whether a checkpoint can read Set-of-Mark
numbers on synthetic coloured squares (digit reading, 2/4/8 marked boxes,
large tags, and a position-words control without marks). Exploratory,
not a published number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
--contextual scores each question on a blank image (cached per question)
and divides that prior out, to test whether the checkpoint's label bias
toward "box 2" can be removed without training.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
Snapshots of two exploratory probe scripts still being run; results not
yet reviewed. Not published numbers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
benchmarks/zoom_search_probe.py replaces C1's oracle box with the model's
own search on V*Bench direct_attributes. Every variant answers on the same
zoom level (a 4x4 grid cell, grown 25%) and differs only in how the cell
is chosen: oracle cell (ceiling), two quadrant choice questions, a
hierarchical yes/no search over quadrants (8 crops), or yes/no on all 16
cells. Exploratory, not a published number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
hier3 runs the yes/no search three levels deep (12 crops) and centres a
square crop on the score-weighted centroid of the last level's cells;
oracle_centred puts the same-size crop on the true target centre, the
ceiling for that crop size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
site-docs/reference/results/detector-regions-and-zoom.md writes up the
marks, crop, zoom-ceiling and zoom-search probes (exploratory CPU runs on
the released checkpoint, no headline numbers). The how-to for the draft
regions layer now warns that numbered marks are mostly not read and points
to the zoom-search results. zoom_search_probe.py: in-progress beam2 variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H
beam2 keeps the top 2 quadrants at the first level: the final crop holds
the target more often (52% -> 63.5%, 19 gained / 6 lost) but accuracy
moves within noise (48.7% -> 51.3%, p = 0.65) for 60% more crops.
Exploratory, not a published number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCUwTdDJhkMRhS21sZ8x8H

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants